package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"regexp"
	"strings"
	"time"
)

const feedUrl = "https://www.yiichina.com"
const loginUrl = "https://www.yiichina.com/login"
const signUrl = "https://www.yiichina.com/ajax/registration"
const voteUrl = "https://www.yiichina.com/ajax/vote"

var (
	username   = flag.String("u", "", "君の名は。 ")
	password   = flag.String("p", "", "你的密码")
	massage    = flag.String("m", "", "你要发的说说")
	toVote     = flag.Bool("v", false, "true:登录后把首页的说全点赞一遍，false:打死不点赞")
	keepOnline = flag.Bool("k", false, "true:登录后保持在线，false:签个到就退出，打死不在线")
)

func main() {
	flag.Parse()
	if *keepOnline {
		more()
		return
	} else {
		once()
	}
}

func once() {
	content, ok := login()
	if !ok {
		return
	}
	fmt.Print("刷新在线成功")
	sign(content)
	feed()
	vote(content)
}

func more() {
	aChan := make(chan uint, 1)
	aChan <- 1
	timer := time.NewTicker(53 * time.Second)

	for {
		select {
		case <-aChan:
			go once()
			break
		case <-timer.C:
			if len(aChan) < 1 {
				aChan <- 1
			}
			break
		}
	}
}

var loginReg = regexp.MustCompile(`<a .*href="/user"><i class=".*fa-user"></i> 个人主页</a>`)

func login() (string, bool) {
	content := request("GET", loginUrl, nil)
	if loginReg.MatchString(content) {
		return content, true
	}
	data := url.Values{
		"LoginForm[username]":   {*username},
		"LoginForm[password]":   {*password},
		"LoginForm[rememberMe]": {"0"},
		"login-button":          {""},
	}
	content = request("POST", loginUrl, strings.NewReader(data.Encode()))
	if loginReg.MatchString(content) {
		fmt.Print("登录成功")
		return content, true
	}
	fmt.Print("登录失败")
	return content, false
}

func sign(content string) {
	reg := regexp.MustCompile(`<a class="btn.+">.+今日已签到.*</a>`)
	if reg.MatchString(content) {
		return
	}
	request("POST", signUrl, strings.NewReader(url.Values{"_csrf": {csrf}}.Encode()))
	fmt.Print("签到成功")
}

func feed() {
	if *massage == "" {
		return
	}
	request("POST", feedUrl, strings.NewReader(url.Values{"Feed[content]": {*massage}}.Encode()))
	fmt.Print("发布签到说说成功")
}

func vote(html string) {
	if !*toVote {
		return
	}
	reg := regexp.MustCompile(`<a class="vote up".+data-type="(\w+)".+data-id="(\d+)".+>.+</a>`)
	if reg.MatchString(html) {
		fmt.Print("说说匹配成功")
	}
	for _, value := range reg.FindAllStringSubmatch(html, 20) {
		data := url.Values{
			"action": {"up"},
			"type":   {value[1]},
			"id":     {value[2]},
		}
		request("POST", voteUrl, strings.NewReader(data.Encode()))
	}
}

//###################################################//

var client = http.Client{
	Timeout: time.Second * 10,
}
var header = map[string]string{
	"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
	"Accept-Language":           "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
	"Cache-Control":             "no-cache",
	"Connection":                "keep-alive",
	"Pragma":                    "no-cache",
	"DNT":                       "1",
	"Upgrade-Insecure-Requests": "1",
	"Referer":                   "https://www.yiichina.com",
	"User-Agent":                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko)",
	"Content-Type":              "application/x-www-form-urlencoded",
	"X-Requested-With":          "XMLHttpRequest",
	"php":                       "dont black me",
}

func request(method, url string, body io.Reader) (content string) {
	req, _ := http.NewRequest(method, url, body)
	for key, value := range header {
		req.Header.Set(key, value)
	}
	req.Header.Set("X-CSRF-Token", csrf)
	if url != signUrl {
		req.Header.Del("X-Requested-With")
	}
	if client.Jar == nil {
		jar, _ := cookiejar.New(nil)
		client.Jar = jar
	}
	resp, err := client.Do(req)
	if err != nil {
		return ""
	}
	defer resp.Body.Close()

	buf, _ := ioutil.ReadAll(resp.Body)
	html := string(buf)
	handleCsrf(resp, html)
	return html
}

var csrf = "假令风歇时下来，犹能簸却沧溟水"

func handleCsrf(resp *http.Response, content string) {
	if !strings.Contains(resp.Header.Get("content-type"), "text/html") &&
		!strings.Contains(resp.Header.Get("Content-Type"), "text/html") {
		return
	}
	if content == "" {
		return
	}
	var reg = regexp.MustCompile(`<meta name="csrf-token" content="(.+)">`)
	if match := reg.FindStringSubmatch(content); len(match) == 2 {
		csrf = match[1]
	}
}
